#ifndef GAME_ANIMATION_GRID_GRID_CELL_H
#define GAME_ANIMATION_GRID_GRID_CELL_H
//
// Game Animation.
// Copyright (C) 2007 Department of Computer Science, University of Copenhagen
//
#include <animation/configuration.h>

#include <vector>
#include <cassert>

namespace animation
{

  /**
   * The Grid Cell class.
   * The grid cell stores a sub-part of the world geometry. This
   * is stored as a bunch of geometry layers. The grid cell
   * also holds a tight fitting world coordinate system AABB.
   */
  template<typename types>
  class GridCell
  {
  public:

    typedef typename types::grid_type       grid_type;
    typedef typename types::cell_type       cell_type;
    typedef typename types::index_type      index_type;
    typedef typename types::aabb_type       aabb_type;
    typedef typename types::real_type       real_type;
    typedef typename types::vector3_type    vector3_type;
    typedef typename types::geometry_type   geometry_type;
    typedef std::vector<geometry_type>      geometry_container;
  protected:

    grid_type  *       m_owner;      ///< A pointer to the virtual grid where this cell is stored.
    index_type         m_i;          ///< The global cell indices of this cell.
    index_type         m_j;          ///< The global cell indices of this cell.
    index_type         m_s;          ///< The global cell indices of this cell.
    index_type         m_t;          ///< The global cell indices of this cell.
    geometry_container m_geometry;   ///< Geometries for each layer in cell.
    real_type          m_depth;      ///< Depth value of cell, ie. distance from camera to center of cell.
    aabb_type          m_aabb;       ///< AABB enclosing all the geometry of this cell.
    bool               m_visible;    ///< Boolean flag telling whether the cell is visible or not.


  public:

	bool               m_occlude_testet;

    index_type & i()  { return m_i;}
    index_type & j()  { return m_j;}
    index_type const & i() const { return m_i;}
    index_type const & j() const { return m_j;}

    index_type & s()  { return m_s;}
    index_type & t()  { return m_t;}
    index_type const & s() const { return m_s;}
    index_type const & t() const { return m_t;}

    grid_type * & owner() {return m_owner;}
    grid_type * const & owner() const {return m_owner;}

    real_type & depth() {return m_depth;}
    real_type const & depth() const {return m_depth;}

    bool & visible() {return m_visible;}
    bool const & visible() const {return m_visible;}

  public:
    void clear(){ m_geometry.clear(); }
    geometry_type & get_geometry(index_type const & idx){ return m_geometry[idx]; }
    index_type geometries() const { return m_geometry.size(); }

    geometry_type & create_geometry()
    {
      m_geometry.push_back(geometry_type());
      return m_geometry[m_geometry.size()-1];
    }

  public:

    bool operator<(cell_type const & cell)const
    {
      if(this->m_depth < cell.depth())
        return true;
      return false;
    }

  public:

    aabb_type &       get_aabb()         { return m_aabb;          };
    aabb_type const & get_aabb()   const { return m_aabb;          };
    vector3_type      get_center() const { return m_aabb.center(); };

  };

} // namespace animation

// GAME_ANIMATION_GRID_GRID_CELL_H
#endif
